<!--
 * @Author: 吴世扬
 * @Date: 2023-02-02 09:56:07
 * @LastEditors: 吴世扬 18368095041@163.com
 * @LastEditTime: 2025-04-09 11:27:34
 * @FilePath: /vue3-admin/src/components/ui/CustomPageSelect/CustomPageSelect.vue
 * @Description: 分页选择器
-->

<script lang="ts" setup>
import { computed, ref } from 'vue';
import { Select } from '@element-plus/icons-vue';

type ValueType = Record<string, any>;

const props = withDefaults(
    defineProps<{
        modelValue: ValueType[];
        labelKey: string;
        valueKey: string;
        remoteMethod: (val: string) => void;
        options: Record<string, any>[];
        page: number;
        pageSize?: number;
        total: number;
        multiple?: boolean;
        disabled?: boolean;
        limit?: number;
    }>(),
    {
        pageSize: 10,
        disabled: false
    }
);

const { valueKey, labelKey } = toRefs(props);

const emits = defineEmits<{
    (event: 'update:model-value', value: ValueType[]): void;
    (event: 'update:page', value: number): void;
    (event: 'update:pageSize', value: number): void;
    (event: 'change', value: ValueType[]): void;
}>();

const searchVal = ref('');
const modelVal = ref([]); // 避免el-select删除标签事件出错

// 移出某项
const handleRemove = (index?: number) => {
    if (index !== undefined) {
        const value = [
            ...props.modelValue.slice(0, index),
            ...props.modelValue.slice(index + 1)
        ];
        console.log(value);
        emits('update:model-value', value);
        emits('change', value);
    }
};

const handleSelectChange = (val: ValueType[]) => {
    console.log(val);
    const index = props.modelValue.findIndex((item) => {
        console.log(item[valueKey.value]);
        return item[valueKey.value] === val[0][valueKey.value];
    });
    if (index === -1) {
        let value = [];
        if (props.limit === 1) {
            // 单选
            value = val;
        } else {
            if (props.limit && props.modelValue.length >= props.limit) {
                return;
            }
            value = props.multiple ? [...props.modelValue, ...val] : [...val];
        }
        emits('update:model-value', value);
        emits('change', value);
    } else {
        handleRemove(index);
        // ElMessage({
        //     type: 'warning',
        //     message: '该项已选择'
        // });
    }
};

const selectedValues = computed(() => {
    return props.modelValue.map((it) => it[valueKey.value]);
});
</script>

<template>
    <div class="custom-page-select-container">
        <el-select
            :model-value="modelVal"
            style="width: 100%"
            placeholder="请搜索选择"
            :value-key="valueKey"
            remote
            filterable
            default-first-option
            remote-show-suffix
            multiple
            :remote-method="
                (val: string) => {
                    searchVal = val;
                    emits('update:page', 1);
                    props.remoteMethod(val);
                }
            "
            @change="handleSelectChange"
            :disabled="disabled"
        >
            <template #prefix>
                <div class="tags-box">
                    <el-tag
                        v-for="(tag, index) in props.modelValue"
                        class="mr-[10px] mb-[10px]"
                        :key="tag[valueKey]"
                        @close="() => handleRemove(index)"
                        :closable="!disabled"
                    >
                        <slot name="label" :row="tag">
                            {{
                                labelKey
                                    ? tag[labelKey]
                                    : '请提供props.labelKey'
                            }}
                        </slot>
                    </el-tag>
                </div>
            </template>
            <template #default>
                <el-option
                    v-for="item in options"
                    :key="item[valueKey]"
                    :label="labelKey ? item[labelKey] : '请提供props.labelKey'"
                    :value="item"
                    :disabled="item.disabled"
                >
                    <slot name="option" :row="item">
                        <div
                            class="flex-row ai-center jc-between"
                            :class="[
                                selectedValues.includes(item[valueKey]) &&
                                    'custom-page-select-active'
                            ]"
                        >
                            <slot name="option-text" :row="item">
                                <span>
                                    {{
                                        labelKey
                                            ? item[labelKey]
                                            : '请提供props.labelKey'
                                    }}
                                </span>
                            </slot>
                            <span
                                v-if="selectedValues.includes(item[valueKey])"
                            >
                                <el-icon>
                                    <Select />
                                </el-icon>
                            </span>
                        </div>
                    </slot>
                </el-option>
                <template v-if="props.total > 0">
                    <div
                        class="custom-page-select-pagination-placeholder"
                    ></div>
                    <div class="custom-page-select-pagination">
                        <el-pagination
                            layout="prev, pager, next"
                            :total="props.total"
                            :current-page="props.page"
                            :page-size="props.pageSize"
                            @update:current-page="
                                (val) => {
                                    emits('update:page', val);
                                    props.remoteMethod(searchVal);
                                }
                            "
                        />
                    </div>
                </template>
            </template>
        </el-select>
    </div>
</template>

<style lang="scss">
.custom-page-select-active {
    font-weight: 700;
    color: var(--el-color-primary);
}

.el-select-dropdown {
    position: relative;
}

.custom-page-select-pagination-placeholder {
    height: 48px;
}

.custom-page-select-pagination {
    position: absolute;
    bottom: 0;
    left: 0;
    display: flex;
    flex-direction: row;
    align-items: center;
    justify-content: center;
    width: 100%;
    height: 48px;
    background: #fff;
    border-top: 1px solid #eee;
}
</style>

<style lang="scss" scoped>
.custom-page-select-container {
    width: 100%;

    .tags-box {
        display: flex;
        flex-direction: column;
        padding-top: 10px;
    }
}
</style>
